package com.duoec.magichour.core.web.filter;

import com.alibaba.fastjson.JSON;
import com.duoec.magichour.core.utils.UUIDUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by ycoe on 17/6/25.
 */
public class LoggerFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(LoggerFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //Nothing to do
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String requestUri = request.getRequestURI();
        Map<String, String> requestMap = this.getTypeSafeRequestMap(request);
        String headerToString = headerToString(request);
        String sessionId = request.getHeader("session-id");
        if(sessionId == null) {
            sessionId = UUIDUtils.generateUUID();
        }

        MDC.put("sessionId", sessionId);
        //加入全局变量

        logger.info("[{}]URI:{}, params:{},headers:{}",
                request.getMethod(),
                requestUri,
                requestMap, headerToString);

        long startTime = System.currentTimeMillis();
        try {
            filterChain.doFilter(request, servletResponse);
        } catch (Exception e) {
            logger.error("LoggerFilter exception: ", e);
        }
        long endTime = System.currentTimeMillis();
        long elapsed = endTime - startTime;
        if (elapsed > 800) {
            String host = request.getHeader("Host");
            logger.info("慢请求:[{}]URI:{},status={},time:{}ms",
                    request.getMethod(),
                    host + requestUri,
                    response.getStatus(),
                    elapsed
            );
        } else {
            logger.info("[{}]URI:{},status={},time:{}ms",
                    request.getMethod(),
                    requestUri,
                    response.getStatus(),
                    elapsed
            );
        }
    }

    private Map<String, String> getTypeSafeRequestMap(HttpServletRequest request) {
        Map<String, String> typesafeRequestMap = new HashMap<>();
        Enumeration<?> requestParamNames = request.getParameterNames();
        while (requestParamNames.hasMoreElements()) {
            String requestParamName = (String) requestParamNames.nextElement();
            String requestParamValue = request.getParameter(requestParamName);
            typesafeRequestMap.put(requestParamName, requestParamValue);
        }
        return typesafeRequestMap;
    }

    private String headerToString(HttpServletRequest request) {
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames == null) {
            return "";
        }
        Map<String, Object> headerMap = new HashMap<>();
        while (headerNames.hasMoreElements()) {
            String header = headerNames.nextElement();

            headerMap.put(header, request.getHeader(header));
        }
        return JSON.toJSONString(headerMap);
    }

    @Override
    public void destroy() {
        MDC.remove("sessionId");
    }
}
